package me.khrystal.rxnews.module.news.model;

import com.socks.library.KLog;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import me.khrystal.rxnews.app.App;
import me.khrystal.rxnews.callback.RequestCallback;
import me.khrystal.rxnews.greendao.NewsChannelTable;
import me.khrystal.rxnews.greendao.NewsChannelTableDao;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.schedulers.Schedulers;

/**
 * usage:
 * author: kHRYSTAL
 * create time: 16/4/29
 * update time:
 * email: 723526676@qq.com
 */
public class INewsChannelInteractorImpl implements INewsChannelInteractor<Map<Boolean,List<NewsChannelTable>>>{
    @Override
    public Subscription channelDbOperate(final RequestCallback<Map<Boolean, List<NewsChannelTable>>> callback, final String channelName, final Boolean selectState) {


        return Observable
                .create(new Observable.OnSubscribe<Map<Boolean, List<NewsChannelTable>>>() {
                    @Override
                    public void call(Subscriber<? super Map<Boolean, List<NewsChannelTable>>> subscriber) {

                        final NewsChannelTableDao dao = ((App)App.getContext())
                                .getDaoSession().getNewsChannelTableDao();

                        if (selectState == null){
                            KLog.e("init get selected channel");
                            HashMap<Boolean,List<NewsChannelTable>> map = new HashMap<Boolean, List<NewsChannelTable>>();
                            map.put(true,dao.queryBuilder()
                                .where(NewsChannelTableDao.Properties.NewsChannelSelect.eq(true))
                                .orderAsc(NewsChannelTableDao.Properties.NewsChannelIndex)
                                .build().list());
                            map.put(false,dao.queryBuilder()
                                .where(NewsChannelTableDao.Properties.NewsChannelSelect.eq(false))
                                .orderAsc(NewsChannelTableDao.Properties.NewsChannelIndex)
                                .build().list());
                            subscriber.onNext(map);
                        }else {
                            if (selectState){
                                KLog.e("increase:" + channelName + ";" + selectState);
                                final NewsChannelTable table = dao.queryBuilder()
                                        .where(NewsChannelTableDao.Properties.NewsChannelName
                                                .eq(channelName)).unique();
                                //oldPos
                                final  int originPos = table.getNewsChannelIndex();
                                //nowPos
                                final  long toPos = dao.queryBuilder()
                                        .where(NewsChannelTableDao.Properties.NewsChannelSelect
                                        .eq(true)).buildCount().count();
                                //找到比他位置小的没被选中的
                                final List<NewsChannelTable> smallChannelTables = dao.queryBuilder()
                                        .where(NewsChannelTableDao.Properties.NewsChannelIndex
                                        .lt(originPos),
                                                NewsChannelTableDao.Properties.NewsChannelSelect
                                        .eq(false)).build().list();
                                for (NewsChannelTable s : smallChannelTables){
                                    s.setNewsChannelIndex(s.getNewsChannelIndex() + 1);
                                    dao.update(s);
                                }
                                //更新数据
                                table.setNewsChannelSelect(true);
                                table.setNewsChannelIndex((int)toPos);
                                dao.update(table);
                            }else {
                                KLog.e("delete: " + channelName + ";" + selectState);
                                final NewsChannelTable table = dao.queryBuilder()
                                        .where(NewsChannelTableDao.Properties.NewsChannelName
                                        .eq(channelName)).unique();
                                final int originPos = table.getNewsChannelIndex();

                                final int nowPos = dao.loadAll().size()-1;

                                final List<NewsChannelTable> unSelectChannels = dao.queryBuilder()
                                        .where(NewsChannelTableDao.Properties.NewsChannelSelect
                                        .eq(false)).build().list();
                                for (NewsChannelTable s : unSelectChannels){
                                    s.setNewsChannelIndex(s.getNewsChannelIndex() - 1);
                                    dao.update(s);
                                }
                                //选中的并且位置比他大的
                                final  List<NewsChannelTable> bigChannels = dao.queryBuilder()
                                        .where(NewsChannelTableDao.Properties.NewsChannelSelect
                                        .eq(true),
                                                NewsChannelTableDao.Properties.NewsChannelIndex
                                        .gt(originPos)).build().list();
                                for (NewsChannelTable b:bigChannels){
                                    b.setNewsChannelIndex(b.getNewsChannelIndex() - 1);
                                    dao.update(b);
                                }

                                table.setNewsChannelSelect(false);
                                table.setNewsChannelIndex(nowPos);
                                dao.update(table);
                            }
                            subscriber.onCompleted();
                        }
                    }
                }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(new Action0() {
                    @Override
                    public void call() {
                        if (selectState == null){
                            callback.beforeRequest();
                        }
                    }
                }).subscribe(new Subscriber<Map<Boolean, List<NewsChannelTable>>>() {
                    @Override
                    public void onCompleted() {
                        callback.requestComplete();
                    }

                    @Override
                    public void onError(Throwable e) {
                        KLog.e(e.getLocalizedMessage() + "\n" + e);
                        callback.requestError(
                                e.getLocalizedMessage() + "\n" + e);
                    }

                    @Override
                    public void onNext(Map<Boolean, List<NewsChannelTable>> tableDaos) {
                        callback.requestSuccess(tableDaos);
                    }
                });
    }

    @Override
    public Subscription channelDbSwap(RequestCallback callback, final int fromPos, final int toPos) {
        return Observable.create(new Observable.OnSubscribe<Object>() {
            @Override
            public void call(Subscriber<? super Object> subscriber) {
                final NewsChannelTableDao dao = ((App)App.getContext())
                        .getDaoSession().getNewsChannelTableDao();

                final NewsChannelTable fromChannel = dao.queryBuilder()
                        .where(NewsChannelTableDao.Properties.NewsChannelIndex.eq(fromPos))
                        .unique();
                final int fromPosition = fromChannel.getNewsChannelIndex();

                final NewsChannelTable toChannel = dao.queryBuilder()
                        .where(NewsChannelTableDao.Properties.NewsChannelIndex.eq(toPos))
                        .unique();

                final int toPosition = toChannel.getNewsChannelIndex();

                if (Math.abs(fromPosition-toPosition) == 1){
                    KLog.e("相邻交换 只需要调整位置");
                    fromChannel.setNewsChannelIndex(toPosition);
                    toChannel.setNewsChannelIndex(fromPosition);
                    dao.update(fromChannel);
                    dao.update(toChannel);
                }else if (fromPosition - toPosition >0){
                    KLog.e("开始的位置大于要去的位置 选中的前移");
                    final List<NewsChannelTable> moveChannels = dao.queryBuilder()
                            .where(NewsChannelTableDao.Properties.NewsChannelIndex
                                    //eg. 2,3,4,5 -> 5,2,3,4
                            .between(toPosition, fromPosition-1)).build().list();
                    for (NewsChannelTable c : moveChannels){
                        c.setNewsChannelIndex(c.getNewsChannelIndex() + 1);
                        dao.update(c);
                    }
                    fromChannel.setNewsChannelIndex(toPosition);
                    dao.update(fromChannel);
                }else if (fromPosition - toPosition < 0){
                    KLog.e("开始位置小于要去的位置 选中的后移");
                    final List<NewsChannelTable> moveChannels = dao.queryBuilder()
                            .where(NewsChannelTableDao.Properties.NewsChannelIndex
                                    .between(fromPos+1,toPos)).build().list();
                    for (NewsChannelTable c : moveChannels){
                        c.setNewsChannelIndex(c.getNewsChannelIndex() - 1);
                        dao.update(c);
                    }
                    fromChannel.setNewsChannelIndex(toPosition);
                    dao.update(fromChannel);
                }
                subscriber.onCompleted();
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe();
    }
}
